﻿using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Windows.Markup;
using Mitosoft.Definitions.Data;
using Mitosoft.Definitions.ViewModels;
using Mitosoft.TextFileReader;
using TextFileReaderModule.Interfaces;
using TextFileReaderModule.Services;
using TextFileReaderModule.ViewModels;

namespace TextFileReaderModule.Manager
{
  public class MultipleFilesDataManager : BaseViewModel
  {
    #region constants

    /// <summary>
    /// Size of cache used to store line positions.
    /// </summary>
    protected const uint LINE_POSITIONS_CACHE_SIZE = 1024;

    /// <summary>
    /// Size of cache used to store line contents.
    /// </summary>
    protected const uint LINE_CONTENT_CACHE_SIZE = 1024;

    #endregion

    #region fields

    /// <summary>
    /// Represents <see cref="CachedCollectionBlockDataProvider"/>
    /// </summary>
    protected CachedCollectionBlockDataProvider<IGenericDataBlockItem<string>, string>
      _cachedCollectionBlockDataProvider;

    /// <summary>
    /// Represents <see cref="Files"/>
    /// </summary>
    protected SortedDictionary<int, string> _files;

    /// <summary>
    /// Represents the service being able to store and to retrieve comments.
    /// </summary>
    protected readonly ICommentService _commentService = new CommentService();

    /// <summary>
    /// Represents the manager responsible to generate and to store the view model instances.
    /// </summary>
    protected readonly GenericDataBlockItemViewModelManager _genericDataBlockItemViewModelManager;

    /// <summary>
    /// Represents the providers delivering data from the text files.
    /// </summary>
    protected Dictionary<int, ICacheableDataBlockProvider<IGenericDataBlockItem<string>, string>> _textFilesReaderProvider = new Dictionary<int, ICacheableDataBlockProvider<IGenericDataBlockItem<string>, string>>();

    #endregion

    #region constructors

    /// <summary>
    /// Creates a new <see cref="MultipleFilesDataManager"/> instance.
    /// </summary>
    public MultipleFilesDataManager()
    {
      _genericDataBlockItemViewModelManager = new GenericDataBlockItemViewModelManager(_commentService);
    }

    #endregion

    #region properties

    /// <summary>
    /// Provides cached data representing the selected files.
    /// </summary>
    public CachedCollectionBlockDataProvider<IGenericDataBlockItem<string>, string> CachedCollectionBlockDataProvider
    {
      get { return _cachedCollectionBlockDataProvider; }
      protected set { _cachedCollectionBlockDataProvider = value; }
    }

    /// <summary>
    /// Represents the files we want to see in editor.
    /// </summary>
    public SortedDictionary<int, string> Files
    {
      get { return _files; }

      set
      {
        _files = value;

        _commentService.Clear();
        _genericDataBlockItemViewModelManager.Clear();
        _textFilesReaderProvider.Clear();

        if ( value == null || !value.Any() )
        {
          if (CachedCollectionBlockDataProvider != null)
            CachedCollectionBlockDataProvider.DataBlockItemInstanceRequest -= OnNewTextFilesReaderItemInstance;

          CachedCollectionBlockDataProvider = null;
        }
        else
        {
          foreach (KeyValuePair<int, string> orderAndSelectedFilePair in value)
          {
            var newTextFileReader = 
              new TextFileReader(
                orderAndSelectedFilePair.Value,
                LINE_POSITIONS_CACHE_SIZE,
                LINE_CONTENT_CACHE_SIZE,
                orderAndSelectedFilePair.Key);

            _textFilesReaderProvider[orderAndSelectedFilePair.Key] = newTextFileReader;
          }

          CachedCollectionBlockDataProvider = 
            new CachedCollectionBlockDataProvider<IGenericDataBlockItem<string>, string>(
              _textFilesReaderProvider, LINE_CONTENT_CACHE_SIZE, SynchronizationContext.Current);

          CachedCollectionBlockDataProvider.DataBlockItemInstanceRequest += OnNewTextFilesReaderItemInstance;
        }

        HandlePropertyChanged();
        // ReSharper disable once ExplicitCallerInfoArgument
        HandlePropertyChanged("CachedCollectionBlockDataProvider");
      }
    }

    /// <summary>
    /// Represents the service handling comments for THIS file.
    /// </summary>
    public ICommentService CommentService
    {
      get { return _commentService; }
    }

    #endregion

    #region methods

    /// <summary>
    /// The text file reader returned a new instance which will be converted
    /// in a <see cref="GenericDataBlockItemViewModel"/> view model.
    /// </summary>
    /// <param name="datablockitem">Instance created from the text file reader.</param>
    /// <param name="sourceIndex">Represents the source index.</param>
    /// <returns>Converted view model.</returns>
    protected IGenericDataBlockItem<string> OnNewTextFilesReaderItemInstance(IGenericDataBlockItem<string> datablockitem, int sourceIndex)
    {
      return
        _genericDataBlockItemViewModelManager.GetGenericDataBlockItemViewModel(datablockitem, sourceIndex);
    }

    /// <summary>
    /// Disposes this object.
    /// </summary>
    /// <param name="isDisposing">Represents whether this object is disposing.</param>
    protected override void Dispose(bool isDisposing)
    {
      if (_isDisposed) return;

      if (isDisposing)
      {
        #region dispose managed resources

        if (CachedCollectionBlockDataProvider != null)
          CachedCollectionBlockDataProvider.DataBlockItemInstanceRequest -= OnNewTextFilesReaderItemInstance;

        #endregion
      }

      #region clean up unmanaged resources

      #endregion

      _isDisposed = true;
    }

    #endregion
  }
}
